package besta.moon.sql.expression.function.string;

import besta.moon.MoonException;
import besta.moon.sql.expression.function.FunctionReturnP1StringAndBinary;
import besta.moon.sql.parser.SQLTokenizer;
import besta.moon.MoonCode;

public final class FunctionSubstring extends FunctionReturnP1StringAndBinary {

    @Override
    public final int getFunction() {
        return SQLTokenizer.SUBSTRING;
    }

    @Override
    public final boolean isNull() throws Exception {
        return param1.isNull() || param2.isNull() || param3.isNull();
    }

    @Override
    public final byte[] getBytes() throws Exception {
        if (isNull()) {
            return null;
        }
        byte[] bytes = param1.getBytes();
        int byteLen = bytes.length;
        int start = Math.min(Math.max(0, param2.getInt() - 1), byteLen);
        int length = param3.getInt();
        if (length < 0) {
            throw MoonException.create(MoonCode.SUBSTR_INVALID_LEN, length);
        }
        if (start == 0 && byteLen == length) {
            return bytes;
        }
        if (byteLen > length + start) {
            byte[] b = new byte[length];
            System.arraycopy(bytes, start, b, 0, length);
            return b;
        } else {
            byte[] b = new byte[byteLen - start];
            System.arraycopy(bytes, start, b, 0, b.length);
            return b;
        }
    }

    @Override
    public final String getString() throws Exception {
        if (isNull()) {
            return null;
        }
        String str = param1.getString();
        int strLen = str.length();
        int start = Math.min(Math.max(0, param2.getInt() - 1), strLen);
        int length = param3.getInt();
        if (length < 0) {
            throw MoonException.create(MoonCode.SUBSTR_INVALID_LEN, length);
        }
        length = Math.min(length, strLen - start);
        return str.substring(start, start + length);
    }

}
